import json
import re

import allure
import pytest
import requests
import urllib3
from requests import utils

from config import setting
from config.setting import FILE_PATH
from utils.logging_tool.recordlog import logs
from utils.read_files_tools.read_extract_yaml import ReadYamlData


class SendRequest:
    """ 发送接口请求"""

    def __init__(self):
        self.read = ReadYamlData()
        self.session = requests.Session()
        read_cookie = ReadYamlData(yaml_file=FILE_PATH['EXTRACT']).get_yaml_data()['Cookie']
        self.session.cookies = requests.utils.cookiejar_from_dict(read_cookie)

    @classmethod
    def _text_encode(cls, res_text):
        """
        处理接口返回值出现 unicode 编码时，如：\\u767b
        :param res_text:
        :return:
        """
        match = re.search(r"\\u[0-9a-fA-F]{4}", res_text)
        if match:
            result = res_text.encode().decode('unicode_escape')
        else:
            result = res_text
        return result

    def send_request(self, **kwargs):
        session = self.session
        result = None

        try:
            result = session.request(**kwargs)

            logs.info(f"实际请求url    :{result.request.url}")
            logs.info(f"实际请求method :{result.request.method}")
            logs.info(f"实际请求headers:{result.request.headers}")
            logs.info(f"实际请求body   :{result.request.body}")

            is_json_pattern = r'^\s*[\{\[].*[\}\]]\s*$'
            if re.match(is_json_pattern, result.text) is None:
                logs.info("接口响应信息：非json格式")
            else:
                self._text_encode(result.text)
                logs.info("接口响应信息：%s" % result.text if result.text else result)

        except requests.exceptions.ConnectionError:
            logs.error("ConnectionError--服务器连接异常")
            pytest.fail("接口请求异常，可能是request的连接数过多或请求速度过快导致程序报错！")
        except requests.exceptions.HTTPError:
            logs.error("HTTPError--http异常")
        except requests.exceptions.RequestException as e:
            logs.error(e)
            pytest.fail("请求异常，请检查系统或数据是否正常！")
        return result

    def run_main(self, feature, name, url, case_name, headers, method, cookies=None, files=None, **kwargs):
        """
        发起接口请求
        :param feature：模块名称
        :param name: 接口名称
        :param url: 接口地址
        :param case_name: 测试用例
        :param headers:请求头
        :param method:请求方法
        :param cookies：默认为空
        :param files: 上传文件接口
        :param kwargs: 请求参数，根据yaml文件的参数类型
        :return:
        """
        try:
            # 收集报告日志
            logs.info(f'模块名称：{feature}')
            logs.info(f'接口名称：{name}')
            logs.info(f'测试用例名称：{case_name}')
            logs.info(f'请求地址：{url}')
            logs.info(f'请求方式：{method}')
            logs.info(f'请求头：{headers}')
            req_params = json.dumps(kwargs, ensure_ascii=False, indent=4)
            if "data" in kwargs.keys():
                logs.info(f'请求参数 data：{kwargs["data"]}')
            if "json" in kwargs.keys():
                json_obj = kwargs["json"]
                if isinstance(json_obj, str):
                    json_obj = json.loads(json_obj)
                    kwargs["json"] = json_obj
                json_str = json.dumps(json_obj, ensure_ascii=False)
                logs.info('请求参数 json：' + json_str)
            if "params" in kwargs.keys():
                logs.info(f'请求参数 params：{kwargs["params"]}')
            allure.attach(req_params, '请求参数', allure.attachment_type.JSON)
        except Exception as e:
            logs.error(e)
        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
        response = self.send_request(method=method,
                                     url=url,
                                     headers=headers,
                                     cookies=cookies,
                                     files=files,
                                     timeout=setting.API_TIMEOUT,
                                     verify=False,
                                     **kwargs
                                     )
        return response
